﻿#include <QCoreApplication>
#include <QDebug>
#include <unordered_map>

// 通信设备接口类
class Device
{
public:
    virtual void write() = 0;
    virtual void read() = 0;
};

typedef Device* (*devInstanceGenerator)();

class DevFactory
{
public:
    static DevFactory& getInstance()
    {
        static DevFactory instance;
        return instance;
    }

    const char** getDevMenu(int& num)
    {
        num = m_generators.size();
        const char** arrayHead = new const char*[num];

        int i = 0;
        for (auto g : m_generators)
        {
            size_t bufferSize = g.first.length() + 1;
            char* generatorIdBuffer = new char[bufferSize];
            strncpy_s(generatorIdBuffer, bufferSize, g.first.c_str(), g.first.length());
            arrayHead[i++] = generatorIdBuffer;
        }

        return arrayHead;
    }

    Device* getDevice(const char* name)
    {
        auto it = m_generators.find(name);
        if (it != m_generators.end())
            return it->second();

        return nullptr;
    }

    bool registerGenerator(const char* name, const devInstanceGenerator& funCreate)
    {
        return m_generators.insert(std::make_pair(name, funCreate)).second;
    }

private:
    DevFactory(){}
    DevFactory(const DevFactory&){}
    ~DevFactory(){}

    std::unordered_map<std::string, devInstanceGenerator> m_generators;
};

namespace DevFactoryRegistrations {

    template <typename T>
    class DevFactoryRegistration
    {
    public:
        DevFactoryRegistration(const char* id)
        {
            DevFactory::getInstance().registerGenerator(
            id,
            []() {return static_cast<Device*>(new T()); }
            );
        }
    };
}

///
/// 具体的子类，网口通信类
///
class EthernetDevice : public Device
{
public:
    EthernetDevice()
    {
        qDebug()<<"EthernetDevice construct";
    }

    virtual ~EthernetDevice()
    {
        qDebug()<<"EthernetDevice disconstruct";
    }

    virtual void write()
    {
        qDebug()<<"EthernetDevice write";
    }

    virtual void read()
    {
        qDebug()<<"EthernetDevice read";
    }
};
namespace DevFactoryRegistrations {
    DevFactoryRegistration<EthernetDevice> _EthernetDevice("ethernet");
}

///
/// 具体的子类，串口通信类
///
class UartDevice: public Device
{
public:
    UartDevice()
    {
        qDebug()<<"uartDevice construct";
    }

    virtual ~UartDevice()
    {
        qDebug()<<"uartDevice disconstruct";
    }

    virtual void write()
    {
        qDebug()<<"uartDevice write";
    }

    virtual void read()
    {
        qDebug()<<"uartDevice read";
    }
};
namespace DevFactoryRegistrations {
    DevFactoryRegistration<UartDevice> _UartDevice("uart");
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    int num;
    const char** devItems = DevFactory::getInstance().getDevMenu(num);
    qDebug()<<"register device count:"<<num;
    qDebug()<<"register device name:";
    for(int i=0;i<num;i++)
    {
        qDebug()<<devItems[i];
    }

    Device* dev = DevFactory::getInstance().getDevice("uart");
    if(dev!=nullptr)
    {
        dev->write();
        dev->read();
        //。。。

    }


    return a.exec();
}
